package main;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import debugger.Debugger;

import Environment.*;
import behavior.Parameters;


import java.awt.event.*;
import java.io.*;
import java.lang.reflect.Field;
import java.net.*;

import view.BoidsPanel;
import view.BoundaryPanel;
import view.Canvas;
import view.ParametersandDebuggerPanel;
import view.RangeSlider;


/**
 * Creates an applet that be viewed over the web.
 *
 * @author Robert C. Duvall
 */
@SuppressWarnings("serial")
public class Applet extends JApplet
{
    public static final String MOVINGENTITIES_LABEL = "Number of Boids to create";
    public static final int MIN_MOVINGENTITIES = 1;
    public static final int MAX_MOVINGENTITIES = 100;
    public static final int SET_MOVINGENTITIES = 50;
    public static final int MOVINGENTITIES_SPACING = 5;
    public static final String RADIUS_LABEL = "Radius of Influence";
    public static final int MIN_RADIUS = 0;
    public static final int MAX_RADIUS = 350;
    public static final int SET_RADIUS = 230;
    public static final int RADIUS_SPACING = 50;
    public static final String DISTANCE_LABEL = "Minimum Distance of Separation";
    public static final int MIN_DISTANCE = 0;
    public static final int MAX_DISTANCE = 70;
    public static final int SET_DISTANCE = 20;
    public static final int DISTANCE_SPACING = 10;
    public static final String TRAIL_LABEL = "Length of Trail";
    public static final int MIN_TRAIL = 0;
    public static final int MAX_TRAIL = 30;
    public static final int SET_TRAIL = 10;
    public static final int TRAIL_SPACING = 5;
    
    // animate 25 times per second if possible
    public static final int DEFAULT_DELAY = 1000 / 25;  // in milliseconds

    private Canvas myDisplay;
    private Timer myTimer;
	protected static JFileChooser ourOpenChooser = new JFileChooser(System
			.getProperties().getProperty("user.dir"));
	protected static JFileChooser ourSaveChooser = new JFileChooser(System
			.getProperties().getProperty("user.dir"));
	private Parameters myParameters;
	private Debugger myDebugger;


    /**
     * Initializes the applet --- called by the browser.
     */
    public void init ()
    {
        init(new Dimension(Integer.parseInt(getParameter("width")),
                           Integer.parseInt(getParameter("height"))));
    }
    
    /**
     * Initializes the applet --- called by main.
     */
    public void init (Dimension size)
    {
        myDisplay = new Canvas(size);
        myDisplay.setPreferredSize(size);
        myDisplay.setSize(size);
        myDisplay.setFocusable(true);
        myDisplay.requestFocus();
        
        myParameters = new Parameters(30, 20);
        myDebugger = new Debugger(5);
        
		JMenuBar bar = new JMenuBar();
		bar.add(makeFileMenu());
		setJMenuBar(bar);
        
        getContentPane().add(makeMovingEntitiesPanel(), BorderLayout.SOUTH);
        getContentPane().add(myDisplay, BorderLayout.CENTER);
        getContentPane().add(makeStandardPanel(), BorderLayout.NORTH);
        getContentPane().add(makeParametersandDebuggerPanel(), BorderLayout.EAST);
    }
    
    /**
     * makes the panel holding the buttons for adding moving entities and the slider for adjusting
     * number of moving entities to add
     * @return the panel as described above
     */
    private JPanel makeMovingEntitiesPanel() {
    	RangeSlider numMovingEntitiesSlider = new RangeSlider(MOVINGENTITIES_LABEL, MIN_MOVINGENTITIES, MAX_MOVINGENTITIES, SET_MOVINGENTITIES, MOVINGENTITIES_SPACING);
        BoidsPanel addMovingEntitiesPanel = new BoidsPanel(myDisplay, numMovingEntitiesSlider, myParameters, myDebugger);
        addMovingEntitiesPanel.add(numMovingEntitiesSlider);
        String[] movingEntitiesClassName = {"Prey", "Predator", "Protector"};
        for (String className : movingEntitiesClassName) {
        	addMovingEntitiesPanel.addButton(className);
        }	
        return addMovingEntitiesPanel;
    }
    
    /**
     * makes the panel holding the sliders for the vales in the Parameters and Debugger class
     * @return the panel described above
     */
    private JPanel makeParametersandDebuggerPanel() {
    	ParametersandDebuggerPanel modifyParametersandDebuggerPanel = new ParametersandDebuggerPanel(myParameters, myDebugger);
        modifyParametersandDebuggerPanel.addParameterSlider("myRadius", RADIUS_LABEL, MIN_RADIUS, MAX_RADIUS, SET_RADIUS, RADIUS_SPACING);
        modifyParametersandDebuggerPanel.addParameterSlider("myMinDistance", DISTANCE_LABEL, MIN_DISTANCE, MAX_DISTANCE, SET_DISTANCE, DISTANCE_SPACING);
        modifyParametersandDebuggerPanel.addDebuggerSlider("myMaxTrail", TRAIL_LABEL, MIN_TRAIL, MAX_TRAIL, SET_TRAIL, TRAIL_SPACING);
        return modifyParametersandDebuggerPanel;
    }
    
    /**
     * makes the standard panel that has the radio buttons for the different types 
     * of boundaries and the buttons step, start, pause, and clear.
     * @return the JPanel with the components listed above
     */
    private JPanel makeStandardPanel() {
        
        BoundaryPanel standardPanel = new BoundaryPanel(myDisplay); 
        standardPanel.addBoundaryType("WallBoundary", "Wall Boundary");
        standardPanel.addBoundaryType("InfiniteBoundary", "InfiniteBoundary");
        standardPanel.addBoundaryType("NoBoundary", "No Boundary");
        
        JButton stepButton = new JButton("Step");
        stepButton.addActionListener(new ActionListener()
        {
            public void actionPerformed (ActionEvent e)
            {
                myDisplay.update();
                myDisplay.repaint();
            }
        });
        standardPanel.add(stepButton);
    
        JButton startButton = new JButton("Start");
        startButton.addActionListener(new ActionListener()
        {
            public void actionPerformed (ActionEvent e)
            {
                start();
            }
        });
        standardPanel.add(startButton);
        
        JButton stopButton = new JButton("Pause");
        stopButton.addActionListener(new ActionListener()
        {
            public void actionPerformed (ActionEvent e)
            {
                stop();
            }
        });
        standardPanel.add(stopButton);
        
        JButton clearButton = new JButton("Clear");
        clearButton.addActionListener(new ActionListener()
            {
                public void actionPerformed (ActionEvent e)
                {
                    myDisplay.getEnvironment().clear();
                    myDisplay.repaint();
                }
            });
        standardPanel.add(clearButton);
        
        return standardPanel;
        
    }
    
    
    /**
     * makes the File Menu which is at the top of the applet
     * allows the user to save, open a file, and quit.
     * @return the file Menu which is a JMenu
     */
    private JMenu makeFileMenu() {
		JMenu fileMenu = new JMenu("File");

		fileMenu.add(new AbstractAction("Open File") {
			public void actionPerformed(ActionEvent ev) {
				int retval = ourOpenChooser.showOpenDialog(null);
				if (retval == JFileChooser.APPROVE_OPTION) {
					File file = ourOpenChooser.getSelectedFile();
					/**
					 * TODO: open
					 */
					System.out.println("you chose to open this file: " + file );
				}
			}
		});
		fileMenu.add(new AbstractAction("Save"){
			public void actionPerformed(ActionEvent e) {
				int retval = ourSaveChooser.showSaveDialog(null);
				if (retval == JFileChooser.APPROVE_OPTION) {
					File file = ourSaveChooser.getSelectedFile();
					try {
						PrintWriter pw = new PrintWriter(file, "UTF8");
						/**
						 * TODO: save
						 */
						pw.close();
						System.out.println("saved");
					} catch (FileNotFoundException e1) {
						System.out.println("could not open "+file);
					} catch (UnsupportedEncodingException e2) {
						System.out.println("problem with UTF8 encoding");
					} 
				}
			}
			
		});
		fileMenu.add(new AbstractAction("Quit") {
			public void actionPerformed(ActionEvent ev) {
				System.exit(0);
			}
		});
		return fileMenu;
	}
    
    /**
     * Starts the applet's action, i.e., starts the animation.
     */
    public void start() {
        myTimer = new Timer(DEFAULT_DELAY, 
            new ActionListener()
            {
                public void actionPerformed(ActionEvent e)
                {
                   myDisplay.update();
                   myDisplay.repaint();
                }
            });
        myTimer.start();
    }


    /**
     * Stops the applet's action, i.e., the animation.
     */
    public void stop() {
        myTimer.stop();
    }
}
